package com.seari.custody.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.seari.custody.component.MinIoUtil;
import com.seari.custody.exception.BIZException;
import com.seari.custody.pojo.RecordsSystsemResponse;
import com.seari.custody.pojo.RecordsSystsemResquest;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.util.PublicSuffixMatcher;
import org.apache.http.conn.util.PublicSuffixMatcherLoader;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
public class HttpClientUtil {

    @Value("${record.download}")
    private String recordownload;//档案系统下载接口地址

    @Value("${record.url}")
    private String recordUrl;//档案系统下载接口地址

    private static String fileSystem;

    @Value("${fileSystem}")
    public void setFileSystem(String fileSystem) {
        HttpClientUtil.fileSystem = fileSystem;
    }

    @Autowired
    private MinIoUtil minIoUtil;


    public static final String splash = "\\";
    public static final String root = "C:";

    private static RequestConfig requestConfig = RequestConfig.custom()
            .setSocketTimeout(5000) //15秒后,长等待超时
            .setConnectTimeout(15000)
            .setConnectionRequestTimeout(15000)
            .build();

    private static HttpClientUtil instance = null;

    private HttpClientUtil() {
    }

    public static synchronized HttpClientUtil getInstance() {
        if (instance == null) {
            instance = new HttpClientUtil();
        }
        return instance;
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     */
    public static String sendHttpPost(String httpUrl) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param params  参数(格式:key1=value1&key2=value2)
     */
    public String sendHttpPost(String httpUrl, String params) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求 JSON请求体
     * 获取档案系统的url使用
     *
     * @param httpUrl 地址
     * @param params  JSON字符串
     *                account 同一时间内同时使用文件下载的时候使用admin账户会造成阻塞  目前使用用户工号下载
     */
    public static String sendHttpPostJsonHasHeader(String httpUrl, String params, String account) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        httpPost.setHeader("account", account);
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    /***
     *
     */
//    public static String TechnicalAdvice(String httpUrl, String account,String params) {
//        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
//        httpPost.setHeader("account",account);
//        httpPost
//        try {
//            //设置参数
//            StringEntity stringEntity = new StringEntity(params, "UTF-8");
//            stringEntity.setContentType("application/json");
//            httpPost.setEntity(stringEntity);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return sendHttpPost(httpPost);
//    }


    /**
     * 发送 post请求 JSON请求体
     *
     * @param httpUrl 地址
     * @param params  JSON字符串
     */
    public static String sendHttpPostJson(String httpUrl, String params) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        //  httpPost.setHeader("");
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求 JSON请求体
     *
     * @param httpUrl 地址
     * @param params  JSON字符串
     */
    public String sendHttpPostJson(String httpUrl, JSONObject params) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params.toJSONString(), "UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setHeader("Accept", "*/*");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    //异步发送
    public void sendHttpPostAsync(String httpUrl, String params) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
                try {
                    //设置参数
                    StringEntity stringEntity = new StringEntity(params, "UTF-8");
                    stringEntity.setContentType("application/x-www-form-urlencoded");
                    httpPost.setEntity(stringEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                CloseableHttpClient httpClient = null;
                CloseableHttpResponse response = null;
                try {
                    // 创建默认的httpClient实例.
                    httpClient = HttpClients.createDefault();
                    httpPost.setConfig(requestConfig);
                    // 执行请求
                    httpClient.execute(httpPost);
                } catch (Exception e) {
                    //e.printStackTrace();
                } finally {
                    try {
                        // 关闭连接,释放资源
                        if (response != null) {
                            response.close();
                        }
                        if (httpClient != null) {
                            httpClient.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }

    /**
     * 发送 post请求
     *
     * @param httpUrl 地址
     * @param maps    参数
     */
    public String sendHttpPost(String httpUrl, Map<String, String> maps) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        // 创建参数队列
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        for (String key : maps.keySet()) {
            nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }


    /**
     * 发送Post请求
     *
     * @param httpPost
     * @return
     */
    private static String sendHttpPost(HttpPost httpPost) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            httpPost.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpPost);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            //e.printStackTrace();
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    /**
     * 发送 get请求
     *
     * @param httpUrl
     */
    public static String sendHttpGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
        return sendHttpGet(httpGet);
    }

    /**
     * 发送 get请求Https
     *
     * @param httpUrl
     */
    public String sendHttpsGet(String httpUrl) {
        HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
        return sendHttpsGet(httpGet);
    }

    /**
     * 发送Get请求
     *
     * @param
     * @return
     */
    private static String sendHttpGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    /**
     * 根据url下载文件，保存到filepath中
     *
     * @param url
     * @param filepath
     * @return
     */
    public static String download(String url, String filepath) {
        try {
            CloseableHttpClient client = HttpClients.createDefault();
            HttpGet httpget = new HttpGet(url);
            CloseableHttpResponse response = client.execute(httpget);
            //System.out.println("cdshi="+response.getHeaders("Content-Disposition").);

            HttpEntity entity = response.getEntity();
            InputStream is = entity.getContent();
            if (filepath == null) {
                filepath = getFilePath(response);
            }

            File file = new File(filepath);
            file.getParentFile().mkdirs();
            FileOutputStream fileout = new FileOutputStream(file);
            /**
             * 根据实际运行效果 设置缓冲区大小
             */
            byte[] buffer = new byte[10 * 1024];
            int ch = 0;
            while ((ch = is.read(buffer)) != -1) {
                fileout.write(buffer, 0, ch);
            }
            is.close();
            fileout.flush();
            fileout.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取response要下载的文件的默认路径
     *
     * @param response
     * @return
     */
    public static String getFilePath(CloseableHttpResponse response) {
        String filepath = root + splash;
        String filename = getFileName(response);

        if (filename != null) {
            filepath += filename;
        } else {
            filepath += getRandomFileName();
        }
        return filepath;
    }

    /**
     * 获取随机文件名
     *
     * @return
     */
    public static String getRandomFileName() {
        return String.valueOf(System.currentTimeMillis());
    }

    /**
     * 获取response header中Content-Disposition中的filename值
     *
     * @param response
     * @return
     */
    public static String getFileName(CloseableHttpResponse response) {
        Header contentHeader = response.getFirstHeader("Content-Disposition");
        String filename = null;
        if (contentHeader != null) {
            HeaderElement[] values = contentHeader.getElements();
            if (values.length == 1) {
                NameValuePair param = values[0].getParameterByName("filename");
                if (param != null) {
                    try {
                        //filename = new String(param.getValue().toString().getBytes(), "utf-8");
                        filename = URLDecoder.decode(param.getValue(), "utf-8");
                        //filename = param.getValue();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return filename;
    }

    /**
     * 发送Get请求Https
     *
     * @param
     * @return
     */
    private String sendHttpsGet(HttpGet httpGet) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpGet.getURI().toString()));
            DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
            httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    /**
     * 文件上传到档案系统——从minio档案系统读取
     *
     * @param url       minio桶名称
     * @param name      上传的文件名  例如:name.docx
     * @param warehouse 档案系统的库编号  57、58
     * @return
     */
    public static String uploadFilePdf(String url, String name, String warehouse) throws Exception {
        try {
            String result = "";
            String price2 = "";
            MultipartFile uploadFile = new MockMultipartFile(name, name, MediaType.MULTIPART_FORM_DATA_VALUE, Common.getObject(url, name));
            final String newLine = "\r\n";
            final String boundaryPrefix = "--";
            // 定义数据分隔线
            String BOUNDARY = "--------------------------727778009192791556644235";
            // 服务器的域名
            URL urlem = new URL(fileSystem + "?AT_FOLDER_ID=" + warehouse);
            HttpURLConnection conn = (HttpURLConnection) urlem.openConnection();
            // 设置为POST情
            conn.setRequestMethod("POST");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求头参数
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
            conn.setRequestProperty("account", "admin");
            OutputStream out = new DataOutputStream(conn.getOutputStream());
            // 上传文件
            StringBuilder sb = new StringBuilder();
            sb.append(boundaryPrefix);
            sb.append(BOUNDARY);
            sb.append(newLine);
            // 文件参数,file参数名可以随意修改(根据你要上传的文件类型)
            sb.append("Content-Disposition: form-data;name=\"file\";filename=\"" + uploadFile.getOriginalFilename()
                    + "\"" + newLine);
            sb.append("Content-Type:application/octet-stream");
            // 参数头设置完以后需要两个换行，然后才是参数内容
            sb.append(newLine);
            sb.append(newLine);
            // 将参数头的数据写入到输出流中
            out.write(sb.toString().getBytes());
            // 数据输入流,用于读取文件数据
            DataInputStream in = new DataInputStream(uploadFile.getInputStream());
            byte[] bufferOut = new byte[1024 * 8];
            int bytes = 0;
            // 每次读8KB数据,并且将文件数据写入到输出流中
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            // 最后添加换行
            out.write(newLine.getBytes());
            in.close();
            // 定义最后数据分隔线，即--加上BOUNDARY再加上--。
            byte[] end_data = (newLine + boundaryPrefix + BOUNDARY + boundaryPrefix + newLine)
                    .getBytes();
            // 写上结尾标识
            out.write(end_data);
            out.flush();
            out.close();
            // 定义BufferedReader输入流来读取URL的响应
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                result += line; //这里读取的是上边url对应的上传文件接口的返回值，读取出来后，然后接着返回到前端，实现接口中调用接口的方式
            }
            System.out.println("档案系统中返回的值：" + result);
            JSONObject jsonValue = JSON.parseObject(result);
            JSONObject price = jsonValue.getJSONObject("RESPONSE");
            JSONObject price1 = price.getJSONObject("fileInfo");
            price2 = price1.getString("FileId");

            return price2;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            // 为0时为档案系统上传数据异常
            return "0";
        }


    }


    /**
     * 文件上传到档案系统—从本地路径读取
     *
     * @param url       需要上传文件的url地址
     * @param name      上传的文件名 例如:name.docx
     * @param warehouse 档案系统的库编号  57、58
     * @return
     */
    public static String uploadLocalAddress(String url, String name, String warehouse) throws Exception {
        String result = "";
        String price2 = "";
        File file = new File(url);
        InputStream inputStream = new FileInputStream(file);
        MultipartFile uploadFile = new MockMultipartFile(name, name, MediaType.MULTIPART_FORM_DATA_VALUE, inputStream);
        // 换行符
        final String newLine = "\r\n";
        final String boundaryPrefix = "--";
        // 定义数据分隔线
        String BOUNDARY = "--------------------------727778009192791556644235";
        // 服务器的域名
        URL urlem = new URL(fileSystem + "?AT_FOLDER_ID=" + warehouse);
        HttpURLConnection conn = (HttpURLConnection) urlem.openConnection();
        // 设置为POST情
        conn.setRequestMethod("POST");
        // 发送POST请求必须设置如下两行
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setUseCaches(false);
        // 设置请求头参数
        conn.setRequestProperty("connection", "Keep-Alive");
        conn.setRequestProperty("Charset", "UTF-8");
        conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
        conn.setRequestProperty("account", "admin");
        OutputStream out = new DataOutputStream(conn.getOutputStream());
        // 上传文件
        StringBuilder sb = new StringBuilder();
        sb.append(boundaryPrefix);
        sb.append(BOUNDARY);
        sb.append(newLine);
        // 文件参数,file参数名可以随意修改(根据你要上传的文件类型)
        sb.append("Content-Disposition: form-data;name=\"file\";filename=\"" + uploadFile.getOriginalFilename()
                + "\"" + newLine);
        sb.append("Content-Type:application/octet-stream");
        // 参数头设置完以后需要两个换行，然后才是参数内容
        sb.append(newLine);
        sb.append(newLine);
        // 将参数头的数据写入到输出流中
        out.write(sb.toString().getBytes());
        // 数据输入流,用于读取文件数据
        DataInputStream in = new DataInputStream(uploadFile.getInputStream());
        byte[] bufferOut = new byte[1024 * 8];
        int bytes = 0;
        // 每次读8KB数据,并且将文件数据写入到输出流中
        while ((bytes = in.read(bufferOut)) != -1) {
            out.write(bufferOut, 0, bytes);
        }
        // 最后添加换行
        out.write(newLine.getBytes());
        in.close();
        // 定义最后数据分隔线，即--加上BOUNDARY再加上--。
        byte[] end_data = (newLine + boundaryPrefix + BOUNDARY + boundaryPrefix + newLine)
                .getBytes();
        // 写上结尾标识
        out.write(end_data);
        out.flush();
        out.close();
        // 定义BufferedReader输入流来读取URL的响应
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line = null;
        while ((line = reader.readLine()) != null) {
            result += line; //这里读取的是上边url对应的上传文件接口的返回值，读取出来后，然后接着返回到前端，实现接口中调用接口的方式
        }
        System.out.println("档案系统中返回的值：" + result);
        JSONObject jsonValue = JSON.parseObject(result);
        JSONObject price = jsonValue.getJSONObject("RESPONSE");
        JSONObject price1 = price.getJSONObject("fileInfo");
        price2 = price1.getString("FileId");
        return price2;
    }


    /**
     * 档案系统下载文件到minio
     *
     * @param fileEmcId   档案系统文件编号
     * @param fileName    档案系统文件名称
     * @param account     下载人员工号
     * @param bucketName  桶名称
     * @param contentType 文件类型
     */
    public void downRecodeFile(String fileEmcId, String fileName, String account, String bucketName, String contentType) {
        try {
            //第一次请求获取 档案系统下载链接
            //档案系统文件ID
            RecordsSystsemResquest recordsSystsemResquest = new RecordsSystsemResquest();
            recordsSystsemResquest.setFILE_ID(fileEmcId);
            //根据文件下载地址下载文件
            String reponseCon = HttpClientUtil.sendHttpPostJsonHasHeader(recordUrl, JSONObject.toJSONString(recordsSystsemResquest), account);
            //响应
            RecordsSystsemResponse recordsSystsemResponse = JSONObject.parseObject(reponseCon, RecordsSystsemResponse.class);
            String downUrl = recordsSystsemResponse.getRESPONSE();
            //第二次请求 获取文件到本地
            CloseableHttpClient client = HttpClients.createDefault();
            HttpGet httpget = new HttpGet(downUrl);
            CloseableHttpResponse response = client.execute(httpget);
            HttpEntity entity = response.getEntity();
            InputStream is = entity.getContent();
            //把文件放置Minio桶
            minIoUtil.putObject(bucketName, fileName, is, contentType);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 档案系统下载文件返回流
     *
     * @param fileEmcId 档案系统文件编号
     * @param fileName  档案系统文件名称
     * @param account   下载人员工号
     * @return
     */
    public InputStream downRecodeFileAsStream(String fileEmcId, String fileName, String account) {
        try {
            //第一次请求获取 档案系统下载链接
            //档案系统文件ID
            RecordsSystsemResquest recordsSystsemResquest = new RecordsSystsemResquest();
            recordsSystsemResquest.setFILE_ID(fileEmcId);
            //根据文件下载地址下载文件
            String reponseCon = HttpClientUtil.sendHttpPostJsonHasHeader(recordUrl, JSONObject.toJSONString(recordsSystsemResquest), account);
            //响应
            RecordsSystsemResponse recordsSystsemResponse = JSONObject.parseObject(reponseCon, RecordsSystsemResponse.class);
            String downUrl = recordsSystsemResponse.getRESPONSE();
            //第二次请求 获取文件到本地
            CloseableHttpClient client = HttpClients.createDefault();
            HttpGet httpget = new HttpGet(downUrl);
            CloseableHttpResponse response = client.execute(httpget);
            HttpEntity entity = response.getEntity();
            return entity.getContent();
        } catch (Exception e) {
            throw new BIZException("档案系统下载文件失败:" + e.getMessage());
        }
    }

    public static void main(String[] args) {

//        String url = "http://10.1.49.89/DownLoad/index?fileIds=156095&token=00321632bcbd821b47c3a3bfd0cba5073cf7";
////        //HttpClientUtil.sendHttpGet(url);
////        HttpClientUtil.download(url,null);
        String url = "http://10.1.49.89:10003/api/FileUpload/DownFileByFileIDAsync";
        String rep = sendHttpPostJsonHasHeader(url, "{\"FILE_ID\":\"156095\"}", "01010006421");
        RecordsSystsemResquest recordsSystsemResquest = new RecordsSystsemResquest();
        recordsSystsemResquest.setFILE_ID("156095");
        String re = JSONObject.toJSONString(recordsSystsemResquest);
        System.out.println("recordsSystsemResquest===" + re);

        RecordsSystsemResponse recordsSystsemResponse = JSONObject.parseObject(rep, RecordsSystsemResponse.class);
        System.out.println("recordsSystsemResponse===" + recordsSystsemResponse.getRESPONSE());
    }


}
